using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;

using Framework;

namespace SchemaMonitor
{
    [Serializable()]
    public partial class CTextMessageList : List<CTextMessage>
    {
        #region Constructors
        //Basic constructor
        public CTextMessageList() : base() {}
       
        //More efficient memory-allocation if size is known
        public CTextMessageList(int capacity) : base(capacity) {}
        
        //Shares the index (if its already been computed)
        public CTextMessageList(CTextMessageList list) : base(list.Count)
        {
            foreach (CTextMessage i in list)
                base.Add(i);
        }

        //Generic list (eg. from paging control), have to assume type
        public CTextMessageList(IList list) : base(list.Count)
        {
            foreach (CTextMessage i in list)
                base.Add(i);
        }
        #endregion
        
        #region Top/Bottom/Page
        public CTextMessageList Top(int count)
        {
            if (count >= this.Count)
                return this;
            return Page(count, 0); 
        }
        public CTextMessageList Bottom(int count)   
        {
            if (count > this.Count)
                count = this.Count;
            return new CTextMessageList(this.GetRange(this.Count - count - 1, count));
        }
        public CTextMessageList Page(int pageSize, int pageIndex)
        {
            return new CTextMessageList( CUtilities.Page(this, pageSize, pageIndex) );
        }
        #endregion

        #region BulkEditLogic
        public bool HaveSameValue(string propertyName)               { return CReflection.HaveSameValue(this, propertyName); }
        public void SetSameValue( string propertyName, object value) {        CReflection.SetSameValue( this, propertyName, value); }
        #endregion

        #region SortBy
        //Public
        public CTextMessageList SortBy(string propertyName) { return SortBy(propertyName, false); }
        public CTextMessageList SortBy(string propertyName, bool descending)
        {
            CTextMessageList copy = new CTextMessageList(this);
            if (this.Count == 0)    return copy;
            copy.Sort(new CTextMessageList_SortBy(propertyName, descending, this));
            return copy;
        }
        //Private 
        private class CTextMessageList_SortBy : CReflection.GenericSortBy, IComparer<CTextMessage>
        {
            public CTextMessageList_SortBy(string propertyName, bool descending, IList list) : base(propertyName, descending, list) { }
            public int Compare(CTextMessage x, CTextMessage y) { return base.Compare(x, y); }
        }
        #endregion

        #region SaveAll/DeleteAll
        //Use default connection (may be overridden in base class)
        public void SaveAll()   {   if (this.Count > 0) { SaveAll(  this[0].DataSrc);    }    }
        public void DeleteAll() {   if (this.Count > 0) { DeleteAll(this[0].DataSrc);    }    }

        //Use connection supplied
        public void SaveAll(  CDataSrc dataSrc) {   dataSrc.BulkSave(this);    }
        public void DeleteAll(CDataSrc dataSrc) {   dataSrc.BulkDelete(this);  }

        //Use transaction supplied
        public void SaveAll(  IDbTransaction txOrNull)    {   foreach (CTextMessage i in this) {   i.Save(  txOrNull);   }   }
        public void DeleteAll(IDbTransaction txOrNull)    {   foreach (CTextMessage i in this) {   i.Delete(txOrNull);   }   }

        //Use a specified isolation level
        public void SaveAll(  IsolationLevel txIsolationLevel)   {   if (this.Count > 0) { SaveAll(  this[0].DataSrc, txIsolationLevel);  }    }
        public void DeleteAll(IsolationLevel txIsolationLevel)   {   if (this.Count > 0) { DeleteAll(this[0].DataSrc, txIsolationLevel);  }    }

        //Use a specified connection and isolation level
        public void SaveAll(  CDataSrc dataSrc, IsolationLevel txIsolationLevel)   {   dataSrc.BulkSave(  this, txIsolationLevel);  }
        public void DeleteAll(CDataSrc dataSrc, IsolationLevel txIsolationLevel)   {   dataSrc.BulkDelete(this, txIsolationLevel);  }
        #endregion

        #region List of Ids
        List<long> _ids;
        public List<long> Ids
        {
            get
            {
                if (null == _ids)
                {
                    var ids = new List<long>(this.Count);
                    foreach (CTextMessage i in this)
                        ids.Add(i.MessageId);
                    _ids = ids;
                }
                return _ids;
            }
        }
        public CTextMessageList GetByIds(List<long> ids)
        {
            CTextMessageList list = new CTextMessageList(ids.Count);
            foreach (int id in ids)
                if (null != GetById(id))
                    list.Add(GetById(id));
            return list;
        }
        #endregion
        
        #region Cache-Control
        //Main Logic
        public new void Add(CTextMessage item)
        {
            if (null != _index && ! _index.ContainsKey(item.MessageId))
                _index[item.MessageId] = item;
            base.Add(item);
        }
        public new void Remove(CTextMessage item)
        {
            if (null != _index && _index.ContainsKey(item.MessageId))
                _index.Remove(item.MessageId);
            base.Remove(item);
        }
    
        //Supplementary List Overloads
        public void Add(   IList<CTextMessage> itemsToAdd)    {   foreach (CTextMessage i in itemsToAdd)   { Add(   i); }   }
        public void Remove(IList<CTextMessage> itemsToRemove) {   foreach (CTextMessage i in itemsToRemove){ Remove(i); }   }
        #endregion
        
        #region Main Index (on Message)
        public CTextMessage GetById(long message)
        {
            CTextMessage c = null;
            Index.TryGetValue(message, out c);
            return c;
        }
        [NonSerialized]
        private Dictionary<long, CTextMessage> _index;
        private Dictionary<long, CTextMessage> Index
        {
            get
            {
                if (null != _index)
                    if (_index.Count == this.Count)
                        return _index;

                    _index = new Dictionary<long, CTextMessage>(this.Count);
                        foreach (CTextMessage i in this) 
                            _index[i.MessageId] = i;
                return _index;
            }
        }
        #endregion
            
        #region Foreign-Key Indices (Subsets)
        //Index by IsMms
        public CTextMessageList GetByIsMms(bool isMms)
        {
            CTextMessageList temp = null;
            if (! IndexByIsMms.TryGetValue(isMms, out temp))
            {
                temp = new CTextMessageList();
                IndexByIsMms[isMms] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<bool, CTextMessageList> _indexByIsMms;
        private Dictionary<bool, CTextMessageList> IndexByIsMms
        {
            get
            {
                if (null == _indexByIsMms)
                {
                    Dictionary<bool, CTextMessageList> index = new Dictionary<bool, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.IsMms, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.IsMms] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByIsMms = index;
                }
                return _indexByIsMms;
            }
        }
        //Index by ContactName
        public CTextMessageList GetByContactName(string contactName)
        {
            CTextMessageList temp = null;
            if (! IndexByContactName.TryGetValue(contactName, out temp))
            {
                temp = new CTextMessageList();
                IndexByContactName[contactName] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<string, CTextMessageList> _indexByContactName;
        private Dictionary<string, CTextMessageList> IndexByContactName
        {
            get
            {
                if (null == _indexByContactName)
                {
                    Dictionary<string, CTextMessageList> index = new Dictionary<string, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.ContactName, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.ContactName] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByContactName = index;
                }
                return _indexByContactName;
            }
        }
        //Index by Address
        public CTextMessageList GetByAddress(string address)
        {
            CTextMessageList temp = null;
            if (! IndexByAddress.TryGetValue(address, out temp))
            {
                temp = new CTextMessageList();
                IndexByAddress[address] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<string, CTextMessageList> _indexByAddress;
        private Dictionary<string, CTextMessageList> IndexByAddress
        {
            get
            {
                if (null == _indexByAddress)
                {
                    Dictionary<string, CTextMessageList> index = new Dictionary<string, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Address, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Address] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByAddress = index;
                }
                return _indexByAddress;
            }
        }
        //Index by Addresses
        public CTextMessageList GetByAddresses(string addresses)
        {
            CTextMessageList temp = null;
            if (! IndexByAddresses.TryGetValue(addresses, out temp))
            {
                temp = new CTextMessageList();
                IndexByAddresses[addresses] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<string, CTextMessageList> _indexByAddresses;
        private Dictionary<string, CTextMessageList> IndexByAddresses
        {
            get
            {
                if (null == _indexByAddresses)
                {
                    Dictionary<string, CTextMessageList> index = new Dictionary<string, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Addresses, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Addresses] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByAddresses = index;
                }
                return _indexByAddresses;
            }
        }
        //Index by Subject
        public CTextMessageList GetBySubject(string subject)
        {
            CTextMessageList temp = null;
            if (! IndexBySubject.TryGetValue(subject, out temp))
            {
                temp = new CTextMessageList();
                IndexBySubject[subject] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<string, CTextMessageList> _indexBySubject;
        private Dictionary<string, CTextMessageList> IndexBySubject
        {
            get
            {
                if (null == _indexBySubject)
                {
                    Dictionary<string, CTextMessageList> index = new Dictionary<string, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Subject, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Subject] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexBySubject = index;
                }
                return _indexBySubject;
            }
        }
        //Index by Type
        public CTextMessageList GetByType(int type)
        {
            CTextMessageList temp = null;
            if (! IndexByType.TryGetValue(type, out temp))
            {
                temp = new CTextMessageList();
                IndexByType[type] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<int, CTextMessageList> _indexByType;
        private Dictionary<int, CTextMessageList> IndexByType
        {
            get
            {
                if (null == _indexByType)
                {
                    Dictionary<int, CTextMessageList> index = new Dictionary<int, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Type, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Type] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByType = index;
                }
                return _indexByType;
            }
        }
        //Index by Status
        public CTextMessageList GetByStatus(int status)
        {
            CTextMessageList temp = null;
            if (! IndexByStatus.TryGetValue(status, out temp))
            {
                temp = new CTextMessageList();
                IndexByStatus[status] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<int, CTextMessageList> _indexByStatus;
        private Dictionary<int, CTextMessageList> IndexByStatus
        {
            get
            {
                if (null == _indexByStatus)
                {
                    Dictionary<int, CTextMessageList> index = new Dictionary<int, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Status, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Status] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByStatus = index;
                }
                return _indexByStatus;
            }
        }
        //Index by Read
        public CTextMessageList GetByRead(bool read)
        {
            CTextMessageList temp = null;
            if (! IndexByRead.TryGetValue(read, out temp))
            {
                temp = new CTextMessageList();
                IndexByRead[read] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<bool, CTextMessageList> _indexByRead;
        private Dictionary<bool, CTextMessageList> IndexByRead
        {
            get
            {
                if (null == _indexByRead)
                {
                    Dictionary<bool, CTextMessageList> index = new Dictionary<bool, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Read, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Read] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByRead = index;
                }
                return _indexByRead;
            }
        }
        //Index by Locked
        public CTextMessageList GetByLocked(bool locked)
        {
            CTextMessageList temp = null;
            if (! IndexByLocked.TryGetValue(locked, out temp))
            {
                temp = new CTextMessageList();
                IndexByLocked[locked] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<bool, CTextMessageList> _indexByLocked;
        private Dictionary<bool, CTextMessageList> IndexByLocked
        {
            get
            {
                if (null == _indexByLocked)
                {
                    Dictionary<bool, CTextMessageList> index = new Dictionary<bool, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Locked, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Locked] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByLocked = index;
                }
                return _indexByLocked;
            }
        }
        //Index by Date
        public CTextMessageList GetByDate(DateTime date)
        {
            CTextMessageList temp = null;
            if (! IndexByDate.TryGetValue(date, out temp))
            {
                temp = new CTextMessageList();
                IndexByDate[date] = temp;
            }
            return temp;
        }

        [NonSerialized]
        private Dictionary<DateTime, CTextMessageList> _indexByDate;
        private Dictionary<DateTime, CTextMessageList> IndexByDate
        {
            get
            {
                if (null == _indexByDate)
                {
                    Dictionary<DateTime, CTextMessageList> index = new Dictionary<DateTime, CTextMessageList>();
                    CTextMessageList temp = null;
                    foreach (CTextMessage i in this)
                    {
                        if (! index.TryGetValue(i.Date, out temp))
                        {
                            temp = new CTextMessageList();
                            index[i.Date] = temp;
                        }
                        temp.Add(i);
                    }
                    _indexByDate = index;
                }
                return _indexByDate;
            }
        }
        #endregion

    }
}
